package com.rengwuxian.coursecoroutines._1_basics

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.lifecycle.lifecycleScope
import com.rengwuxian.coursecoroutines.common.Contributor
import com.rengwuxian.coursecoroutines.common.gitHub
import com.rengwuxian.coursecoroutines.ui.theme.CourseCoroutinesTheme
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.Disposable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.newFixedThreadPoolContext
import kotlinx.coroutines.newSingleThreadContext
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import kotlin.concurrent.thread
import kotlin.coroutines.EmptyCoroutineContext

/**
 * 学协程有用吗？
 * 协程的定义、协程与线程的关系、「轻量级线程」的本质
 *
 * 并发管理：
 * Java用线程
 * Kotlin用协程
 *
 * 协程封装的好：
 * 线性结构来写异步代码、并发管理也是线性的 = 线性结构来写并发代码（写法很轻量）
 *
 */
class PreviewActivity : ComponentActivity() {
  private val handler = Handler(Looper.getMainLooper())

  @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class)
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    setContent {
      CourseCoroutinesTheme {}
    }

    thread {

    }

    val executor = Executors.newCachedThreadPool()
    executor.execute {

    }

    // 类似与上面的Executors
    val scope = CoroutineScope(EmptyCoroutineContext)
    scope.launch {

    }

    val context = newFixedThreadPoolContext(4, "MyThreadPool")
    val context1 = newSingleThreadContext("MySingleThread")
    val scope1 = CoroutineScope(context)
    context.close()

    GlobalScope.launch {

    }
  }

  private fun callbackStyle() {
    gitHub.contributorsCall("square", "retrofit").enqueue(object : Callback<List<Contributor>> {
      override fun onResponse(
        call: Call<List<Contributor>>, response: Response<List<Contributor>>,
      ) {
        showContributors(response.body()!!)
      }

      override fun onFailure(call: Call<List<Contributor>>, t: Throwable) {
        t.printStackTrace()
      }
    })
  }

  private fun coroutinesStyle() = lifecycleScope.launch {
    val contributors = gitHub.contributors("square", "retrofit")
    showContributors(contributors)
  }

  private fun completableFutureStyleMerge() {
    val future1 = gitHub.contributorsFuture("square", "retrofit")
    val future2 = gitHub.contributorsFuture("square", "okhttp")
    future1.thenCombine(future2) { contributors1, contributors2 ->
      contributors1 + contributors2
    }.thenAccept { mergedContributors ->
      handler.post {
        showContributors(mergedContributors)
      }
    }
  }

  private fun rxStyleMerge(): Disposable {
    val single1 = gitHub.contributorsRx("square", "retrofit")
    val single2 = gitHub.contributorsRx("square", "okhttp")
    return Single.zip(single1, single2) { contributors1, contributors2 ->
      contributors1 + contributors2
    }.observeOn(AndroidSchedulers.mainThread())
      .subscribe(::showContributors)
  }

  private fun coroutinesStyleMerge() = lifecycleScope.launch {
    val contributors1 = async { gitHub.contributors("square", "retrofit") }
    val contributors2 = async { gitHub.contributors("square", "okhttp") }
    showContributors(contributors1.await() + contributors2.await())
  }

  private fun showContributors(contributors: List<Contributor>) = contributors.forEach {
    println("${it.login} has made ${it.contributions} contributions")
  }
}